package com.guokai2012.util;

import com.guokai2012.domain.LineData;
import com.qiniu.util.StringUtils;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.*;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @ClassName ListPanelItem
 * @Description 主面板
 */
public class ListPanelItem extends JTabbedPane {
    private final SimpleDateFormat sdf;
    private List<LineData> dataList;
    private final int emptyLine = 2;
    private final int lineHeight = 30;
    private final String timePlace = "可选择提醒时间...";
    private final String contextPlace = "提醒内容必填...";
    private JPanel basePanel;
    private final Map<Integer, JDialog> showList = new HashMap<>();
    private final MainFrame frame;
    private final GridBagConstraints gbcH = new GridBagConstraints();
    private final GridBagLayout gblH = new GridBagLayout();
    private Consumer<ListPanelItem> callFun;

    public ListPanelItem(MainFrame frame, String sdf) {
        this.frame = frame;
        this.sdf = new SimpleDateFormat(sdf);
        // 在水平方向填充
        this.gbcH.fill = GridBagConstraints.HORIZONTAL;
        this.gbcH.gridx = 0;
        this.gbcH.gridy = 0;
        this.gbcH.weightx = 1;
        this.gbcH.gridwidth = 3;
    }

    /**
     * 初始化 组件
     */
    public void initListPanelItem(List<LineData> data) {
        this.dataList = data.stream().sorted(Comparator.comparing(LineData::getTime,
                Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());
        this.basePanel = new JPanel();
        basePanel.setLayout(gblH);
        JScrollPane scrollPane = new JScrollPane(basePanel);

        addTab("待办事项", null, scrollPane);
        setMnemonicAt(0, KeyEvent.VK_1);
        addTab("已完成事项", null, null);
        setMnemonicAt(1, KeyEvent.VK_2);
        addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                updateTodoPanel();
            }
        });
        initData();
    }

    /**
     * 获取 所有待办数据
     */
    public List<LineData> getDataList() {
        return dataList;
    }

    /**
     * 添加回调函数
     */
    public void addCommitted(Consumer<ListPanelItem> consumer) {
        this.callFun = consumer;
    }

    /**
     * 触发 回调函数
     */
    private void actionCommitted() {
        if (null != this.callFun) {
            this.callFun.accept(this);
        }
    }

    /**
     * 初始 数据，根据数据，生成 待办行 组件
     */
    private void initData() {
        // 初始化 已存储的数据
        int i = 0, size = dataList.size();
        for (; i < size; i++) {
            addLine(i, dataList.get(i));
        }
        // 初始化待输入的数据
        for (; i < size + emptyLine; i++) {
            addLine(i, new LineData());
        }
        // 生成 最后占位行
        gbcH.gridy = i;
        gbcH.weighty = 1;
        basePanel.add(new JPanel().add(new JLabel("~我也是有底线的~", JLabel.CENTER)), gbcH, i);
        updateTodoPanel();
    }

    /**
     * 更新 todoPanel 内容
     */
    private void updateTodoPanel() {
        int sIn = getSelectedIndex();
        Component[] comps = basePanel.getComponents();
        for (int i = 0; i < comps.length; i++) {
            boolean isVisible = true;
            if (comps[i] instanceof LinePanel) {
                LinePanel tmp = (LinePanel) comps[i];
                if (sIn == 1 && !tmp.checkBox.isSelected()) {
                    isVisible = false;
                } else if (sIn == 0 && tmp.checkBox.isSelected()) {
                    isVisible = false;
                }
                if (sIn == 1 && isVisible) {
                    tmp.timeField.setEnabled(false);
                    tmp.textField.setEnabled(false);
                } else if (sIn == 0 && isVisible) {
                    tmp.timeField.setEnabled(true);
                    tmp.textField.setEnabled(true);
                }
                tmp.setVisible(isVisible);
            }
        }
    }

    /**
     * 添加 带输入行的
     */
    private void addEmptyLine() {
        int pt = basePanel.getComponentCount();
        addLine(pt - 1, new LineData());
        gbcH.gridy = pt;
        gbcH.weighty = 1;
        Component component = basePanel.getComponent(pt);
        gblH.setConstraints(component, gbcH);
        basePanel.updateUI();
    }

    /**
     * 添加 一行数据
     */
    private void addLine(int key, LineData item) {
        gbcH.gridy = key;
        gbcH.weighty = 0;
        basePanel.add(new LinePanel(key, item), gbcH, key);
    }


    /**
     * 显示 提示
     */
    public void showTip(int index) {
        if (null != showList.get(index)) {
            showList.get(index).setVisible(true);
            return;
        }
        LinePanel panel = (LinePanel) basePanel.getComponent(index);
        JDialog dialog = new JDialog();
        int y = showList.size() * 70;
        showList.put(index, dialog);

        JPanel basePanel = new JPanel();
        basePanel.setBackground(Color.WHITE);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        basePanel.setLayout(new BorderLayout());

        JLabel label = new JLabel(dataList.get(index).getContext(), JLabel.LEFT);
        label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
        label.setBackground(Color.RED);
        label.setPreferredSize(new Dimension(230, 60));
        label.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                showMain(index);
            }
        });
        basePanel.add(label, BorderLayout.WEST);

        JPanel rPanel = new JPanel(new GridLayout(2, 1));
        rPanel.setPreferredSize(new Dimension(70, 60));
        rPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY));
        JLabel lab = new JLabel("完成", JLabel.CENTER);
        lab.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                panel.checkBox.setSelected(true);
                panel.commitSelect();
                dialog.setVisible(false);
                showList.remove(index);
                updateTipUI();
            }
        });
        rPanel.add(lab);
        JComboBox<String> comboBox = new JComboBox<>();
        comboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED && !"-推迟-".equals(e.getItem())) {
                    long delay = setDelay(e.getItem().toString());
                    panel.item.setRemindTime(new Date(delay));
                    dataList.get(index).setRemindTime(new Date(delay));
                    dialog.setVisible(false);
                    showList.remove(index);
                    actionCommitted();
                    updateTipUI();
                }
            }
        });
        comboBox.addItem("-推迟-");
        comboBox.addItem("1小时");
        comboBox.addItem("10分钟");
        comboBox.addItem("明天");
        rPanel.add(comboBox);
        basePanel.add(rPanel, BorderLayout.EAST);

        dialog.add(basePanel);
        dialog.setBounds(screenSize.width - 310, y, 300, 60);
        dialog.setUndecorated(true);
        dialog.setVisible(true);
    }

    /**
     * 重新刷新 提示框显示位置
     */
    private void updateTipUI() {
        int i = 0;
        for (Integer key : showList.keySet()) {
            JDialog dialog = showList.get(key);
            dialog.setLocation(dialog.getX(), i * 70);
            i++;
        }
    }

    /**
     * 显示 选中的行
     */
    private void showMain(int index) {
        Component[] components = basePanel.getComponents();
        for (int i = 0; i < components.length; i++) {
            if (components[i] instanceof LinePanel) {
                LinePanel panel = (LinePanel) components[i];
                if (i == index) {
                    panel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.RED));
                } else {
                    panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));
                }
            }
        }
        setSelectedIndex(0);
        this.frame.showJFrame();
    }

    /**
     * 处理 推迟提醒设置
     */
    private long setDelay(String item) {
        long millis = System.currentTimeMillis();
        switch (item) {
            case "10分钟":
                millis += 1000 * 60 * 10;
                break;
            case "1小时":
                millis += 1000 * 60 * 60;
                break;
            case "3小时":
                millis += 1000 * 60 * 60 * 3;
                break;
            case "明天":
                millis += 1000 * 60 * 60 * 24;
                break;
            default:
                break;
        }
        return millis;
    }


    /**
     * 行对象
     */
    private class LinePanel extends JPanel {
        private LineData item;
        private int key;
        private JCheckBox checkBox;
        private JTextField textField;
        private JTextField timeField;

        public LinePanel(int key, LineData item) {
            this.key = key;
            this.item = item;
            initLineData();
        }

        /**
         * 生成 行 组件
         */
        private void initLineData() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbcV = new GridBagConstraints();
            gbcV.fill = GridBagConstraints.HORIZONTAL;
            gbcV.gridy = 0;
            setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));

            // checkBox
            this.checkBox = new JCheckBox(null, null, item.getFinish());
            checkBox.setBackground(Color.WHITE);
            checkBox.setPreferredSize(new Dimension(30, lineHeight));
            gbcV.gridx = 0;
            gbcV.weightx = 0.0;
            add(checkBox, gbcV);
            checkBox.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (StringUtils.isNullOrEmpty(textField.getText()) || contextPlace.equals(textField.getText())) {
                        checkBox.setSelected(false);
                        return;
                    }
                    commitSelect();
                }
            });

            // 提醒内容
            String tmpContext = contextPlace;
            if (null != item.getContext() && !"".equals(item.getContext())) {
                tmpContext = item.getContext();
            }
            this.textField = new JTextField(tmpContext);
            textField.setName("task");
            textField.setPreferredSize(new Dimension(200, lineHeight));
            textField.setBorder(null);
            if (item.getFinish()) {
                textField.setEnabled(false);
            }
            gbcV.gridx = 1;
            gbcV.weightx = 1;
            textField.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent e) {
                    doPlaceholder((JTextField) e.getSource());
                }

                @Override
                public void focusLost(FocusEvent e) {
                    doPlaceholder((JTextField) e.getSource());
                    commitContent(false);
                }
            });
            add(textField, gbcV);

            // 提醒时间
            this.timeField = new JTextField(timePlace);
            timeField.setName("time");
            timeField.setPreferredSize(new Dimension(120, lineHeight));
            timeField.setBorder(null);

            gbcV.gridx = 3;
            gbcV.weightx = 0.0;
            add(timeField, gbcV);
            DateTimePicker dateTimePicker = new DateTimePicker(sdf.toPattern(), 200, 200);
            dateTimePicker.setTimeEnable(true).changeDateEvent(new Consumer<DateTimePicker>() {
                @Override
                public void accept(DateTimePicker o) {
                    commitContent(true);
                }
            }).register(timeField);
            if (null != item.getTime()) {
                dateTimePicker.setSelect(item.getTime());
            }
            if (item.getFinish()) {
                timeField.setEnabled(false);
            }
            setForegroundColor(item.getTime());
        }

        /**
         * 处理 placeholder
         */
        private void doPlaceholder(JTextField textField) {
            String text = textField.getText();
            String name = textField.getName();
            if (contextPlace.equals(text) || timePlace.equals(text)) {
                textField.setText(null);
            }
            if (null == text || StringUtils.isNullOrEmpty(text)) {
                if (name.equals("task")) {
                    textField.setText(contextPlace);
                } else {
                    textField.setText(timePlace);
                }
            }
        }

        /**
         * 设置 提醒日期超过后，字体颜色为红色
         */
        private void setForegroundColor(Date time) {
            if (null != time && System.currentTimeMillis() - (60 * 1000) > time.getTime()) {
                textField.setForeground(Color.RED);
                timeField.setForeground(Color.RED);
            } else if (null == time || System.currentTimeMillis() - (60 * 1000) <= time.getTime()) {
                textField.setForeground(Color.BLACK);
                timeField.setForeground(Color.BLACK);
            }
        }

        /**
         * 确认 数据
         */
        private void commitContent(boolean isSelectTime) {
            String content = this.textField.getText();
            if (!StringUtils.isNullOrEmpty(content) && !contextPlace.equals(content)) {
                Date time = sdf.parse(this.timeField.getText(), new ParsePosition(0));
                setForegroundColor(time);
                if (isSelectTime) {
                    // 只设置时间，不触发新增行
                    this.item.setTime(time);
                    this.item.setRemindTime(time);
                    dataList.get(key).setTime(time);
                    dataList.get(key).setRemindTime(time);
                } else {
                    // 判断，是否需要新增行
                    if (key >= dataList.size()) {
                        LineData item = new LineData();
                        item.setContext(content);
                        item.setTime(time);
                        item.setRemindTime(time);
                        dataList.add(item);
                        addEmptyLine();
                    } else {
                        dataList.get(key).setRemindTime(time);
                        dataList.get(key).setTime(time);
                        dataList.get(key).setContext(content);
                    }
                }
                actionCommitted();
            }
        }

        /**
         * 勾选完成、未完成 处理
         */
        private void commitSelect() {
            this.item.setFinish(this.checkBox.isSelected());
            dataList.get(key).setFinish(this.checkBox.isSelected());
            if (this.checkBox.isSelected()) {
                this.item.setFinishTime(new Date());
            } else {
                this.item.setFinishTime(null);
            }
            updateTodoPanel();
            actionCommitted();
        }
    }
}

